home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-10 | 39.1 KB | 1,669 lines |
- /*
- * File: rlocal.r
- * Routines needed for different systems.
- */
-
- /*
- * The following code is operating-system dependent [@rlocal.01].
- * Routines needed by different systems.
- */
-
- #if PORT
- /* place for anything system-specific */
- Deliberate Syntax Error
- #endif /* PORT */
-
- #if AMIGA
- #if LATTICE
- long _STACK = 20000;
- long _MNEED = 200000; /* reserve space for allocation (may be too large) */
- #endif /* LATTICE */
- #if AZTEC_C
- /*
- * abs
- */
- abs(i)
- int i;
- {
- return ((i<0)? (-i) : i);
- }
-
- /*
- * ldexp
- */
- double ldexp(value,exp)
- double value;
- {
- double retval = 1.0;
- if(exp>0) {
- while(exp-->0) retval *= 2.0;
- } else if (exp<0) {
- while(exp++<0) retval = retval / 2.0;
- }
- return value * retval;
- }
-
- /*
- * abort()
- */
- novalue abort()
- {
- fprintf(stderr,"icon error with ICONCORE set\n");
- fflush(stderr);
- exit(1);
- }
-
- #ifdef SystemFnc
-
- /*
- * Aztec C version 3.6 does not support system(), but here is a substitute.
- */
- #include <ctype.h>
-
- #define KLUDGE1 256
- #define KLUDGE2 64
- int system(s)
- char *s;
- {
- char text[KLUDGE1], *cp=text;
- char *av[KLUDGE2];
- int ac = 0;
- int l = strlen(s);
-
- if (l >= KLUDGE1)
- return -1;
- strcpy(text,s);
- av[ac++] = text;
- while(*cp && ac<KLUDGE2-1) {
- if (isspace(*cp)) {
- *cp++ = '\0';
- while(isspace(*cp))
- cp++;
- if (*cp)
- av[ac++] = cp;
- }
- else {
- cp++;
- }
- }
- av[ac] = NULL;
- return fexecv(av[0], av);
- }
- #endif /* SystemFnc */
- #endif /* AZTEC_C */
- #endif /* AMIGA */
-
- #if ARM
-
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "kernel.h"
-
- char *mktemp (const char *);
-
- static char *strdup (const char *);
- static int os_cmd (char *);
- static int cmp_cmd (char *, char *);
-
- #define MAX_PIPE 20
-
- typedef enum
- {
- unopened = 0,
- reading,
- writing
- }
- pipemode;
-
- static struct pipe
- {
- char *command; /* The command being executed */
- char *name; /* The name of the pipe file */
- FILE *fd; /* The file used as a pipe */
- pipemode pmode; /* The open mode of the pipe */
- int retval; /* The return value of the command */
- }
- pipes[MAX_PIPE];
-
- FILE *popen (char *command, char *mode)
- {
- FILE *current;
- char *name;
- int i;
- pipemode curmode;
- int rval = -1;
- char tmp[11];
-
- /* decide on mode */
- if ( mode[1] != 0 )
- return NULL;
- else if ( *mode == 'r' )
- curmode = reading;
- else if ( *mode == 'w' )
- curmode = writing;
- else
- return NULL;
-
- /* Get a slot in the pipes structure */
- for ( i = 0; i < MAX_PIPE; ++i )
- {
- if ( pipes[i].pmode == unopened )
- break;
- }
-
- if ( i >= MAX_PIPE )
- return NULL;
-
- /* Get a file name to use */
- sprintf(tmp, "Pipe%.2d", i);
- name = mktemp(tmp);
-
- if ( name == NULL )
- return NULL;
-
- /*
- * If we're reading, just call system() to get a file filled
- * with output.
- */
-
- if ( curmode == reading )
- {
- char *tmpname;
- int oscmd = os_cmd(command);
- char cmd[256];
- int n;
-
- if (*command == '%')
- {
- oscmd = 1;
- ++command;
- }
-
- if (!oscmd)
- {
- char *s;
-
- while (*command && isspace(*command))
- ++command;
-
- s = command;
-
- while (*s && !isspace(*s))
- ++s;
-
- n = sprintf(cmd, "%.*s > %s%s",
- s - command, command, name, s);
- }
- else
- {
- tmpname = mktemp("PipeTmp");
-
- if (tmpname == NULL)
- {
- free(name);
- return NULL;
- }
-
- n = sprintf(cmd, "%s{ > %s }", command, tmpname);
- }
-
- /* Emergency! Overflow in command buffer! */
- if (n > 255)
- {
- if (oscmd)
- {
- remove(tmpname);
- free(tmpname);
- }
- free(name);
- return NULL;
- }
-
- _kernel_setenv("Sys$ReturnCode", "0");
- rval = system(cmd);
-
- if (rval == _kernel_ERROR)
- {
- remove(tmpname);
- free(tmpname);
- free(name);
- return NULL;
- }
-
- if (oscmd)
- {
- int ch;
- FILE *in = fopen(tmpname, "r");
- FILE *out = fopen(name, "w");
-
- if (in == NULL || out == NULL)
- {
- remove(tmpname);
- free(tmpname);
- free(name);
- return NULL;
- }
-
- /* Strip out CRs from the output */
- while ((ch = getc(in)) != EOF && !ferror(out))
- {
- if (ch != '\r')
- putc(ch, out);
- }
-
- /* Did we succeed? */
- ch = (ferror(in) || ferror(out));
-
- /* Tidy up */
- fclose(in);
- fclose(out);
- remove(tmpname);
- free(tmpname);
-
- if (ch)
- {
- free(name);
- return NULL;
- }
- }
-
- if ( (current = fopen(name,"r")) == NULL )
- {
- free(name);
- return NULL;
- }
- }
- else
- {
- if ( (current = fopen(name,"w")) == NULL )
- {
- free(name);
- return NULL;
- }
- }
-
- pipes[i].command = strdup(command);
- pipes[i].name = name;
- pipes[i].fd = current;
- pipes[i].pmode = curmode;
- pipes[i].retval = rval;
- return current;
- }
-
- #define ReadCat 5
-
- /* Create a temporary file name by adding a directory prefix to file.
- * If the external variable temp_dir is not zero, this directory will be
- * used. Otherwise, the following are used, in order.
- * 1. <Tmp$Dir>
- * 2. &.Tmp
- * 3. The current directory.
- * The function returns zero on an error (temp_dir is not a directory, or
- * malloc() failed), otherwise it returns a malloc-ed string containing
- * the required name.
- */
-
- static char *concat (const char *dir, const char *file);
-
- char *temp_dir = 0;
-
- char *mktemp (const char *file)
- {
- char *dir;
- char *name;
- char buf[11];
- int len = strlen(file);
- _kernel_osfile_block blk;
- _kernel_swi_regs regs;
-
- /* Is the supplied filename a pure file name? */
- if (len > 10)
- return 0;
-
- /* Pad out the supplied filename on the left with a unique ID
- * (Based on the program start time)
- */
- if (len < 10 && _kernel_swi(OS_GetEnv,®s,®s) == NULL)
- {
- int i;
- char *time = (char *)regs.r[2];
-
- strcpy(buf,file);
-
- for (i = len; i < 10; ++i)
- {
- char c = time[(9 - i) >> 1];
-
- if (i & 1)
- c >>= 4;
-
- c &= 0x0F;
- buf[i] = "abcdefghijklmnop"[c];
- }
-
- buf[10] = 0;
-
- file = buf;
- }
-
- /* First, try the supplied directory */
- if ( temp_dir )
- {
- if ( _kernel_osfile(ReadCat,temp_dir,&blk) == 2 )
- return concat(temp_dir,file);
- else
- {
- /* Is it a filing system name only? */
- len = strlen(temp_dir);
-
- if (temp_dir[len-1] != ':')
- return 0;
-
- /* One extra, just in case file == "", for the '@' */
- name = malloc(len + strlen(file) + 2);
-
- if (name == 0)
- return 0;
-
- strcpy(name,temp_dir);
- name[len] = '@';
- name[len+1] = '\0';
-
- if (_kernel_osfile(ReadCat,name,&blk) != 2)
- {
- free(name);
- return 0;
- }
-
- strcpy(&name[len],file);
- return name;
- }
- }
-
- /* Otherwise, go through the list... */
-
- /* First of all, try <Tmp$Dir> */
- if ((dir = getenv("Tmp$Dir")) != 0)
- {
- if (_kernel_osfile(ReadCat,dir,&blk) == 2)
- return concat(dir,file);
- else
- {
- /* Is it a filing system name only? */
- len = strlen(dir);
-
- if (dir[len-1] != ':')
- goto no_go;
-
- /* One extra, just in case file == "", for the '@' */
- name = malloc(len + strlen(file) + 2);
-
- if (name == 0)
- goto no_go;
-
- strcpy(name,dir);
- name[len] = '@';
- name[len+1] = '\0';
-
- if (_kernel_osfile(ReadCat,name,&blk) != 2)
- {
- free(name);
- goto no_go;
- }
-
- strcpy(&name[len],file);
- return name;
- }
- }
-
- no_go:
- /* No <Tmp$Dir>, so try &.Tmp, if it exists */
- if (_kernel_osfile(ReadCat,"&.Tmp",&blk) == 2)
- return concat("&.Tmp",file);
-
- /* Out of luck - use the current directory */
- name = malloc(strlen(file)+1);
- if ( name )
- strcpy(name,file);
-
- return name;
- }
-
- static char *concat (const char *dir, const char *file)
- {
- char *result = malloc(strlen(dir)+strlen(file)+2);
- char *p = result;
-
- if ( result == 0 )
- return 0;
-
- while ( *dir )
- *p++ = *dir++;
-
- *p++ = '.';
- while ( *file )
- *p++ = *file++;
-
- *p = '\0';
-
- return result;
- }
-
- /* ----------------------------------------------------------------- */
-
- #ifdef test
-
- #include <stdio.h>
-
- int main (int argc, char *argv[])
- {
- char *tmp;
-
- if ( argc != 2 && argc != 3 )
- {
- fprintf(stderr,"Usage: %s file [dir]\n",argv[0]);
- return 1;
- }
-
- if ( argc == 3 )
- temp_dir = argv[2];
-
- tmp = mktemp (argv[1]);
-
- printf("Temp file = %s\n", tmp ? tmp : "<Not possible>");
-
- return 0;
- }
-
- #endif
-
- int pclose (FILE *current)
- {
- int rval;
- int i;
-
- /* Get the appropriate slot in thbe pipes structure */
- for ( i = 0; i < MAX_PIPE; ++i )
- {
- if ( pipes[i].fd == current )
- break;
- }
-
- if ( i >= MAX_PIPE )
- return -1;
-
- if ( pipes[i].pmode == reading )
- {
- /* Input pipes are just files we're done with */
- rval = pipes[i].retval;
- fclose(current);
- remove(pipes[i].name);
- }
- else
- {
- /*
- * Output pipes are temporary files we have
- * to cram down the throats of programs.
- */
- char *command = pipes[i].command;
- int oscmd = os_cmd(command);
- int n;
- char cmd[256];
-
- if (*command == '%')
- {
- oscmd = 1;
- ++command;
- }
-
- /* Close the pipe file */
- fclose(current);
-
- /* Create the required command string */
- if (oscmd)
- n = sprintf(cmd, "%s{ < %s }", command, pipes[i].name);
- else
- {
- char *s;
-
- while (*command && isspace(*command))
- ++command;
-
- s = command;
-
- while (*s && !isspace(*s))
- ++s;
-
- n = sprintf(cmd, "%.*s < %s%s",
- s - command, command, pipes[i].name, s);
- }
-
- /* Check for overflow in command buffer */
- if (n > 255)
- rval = -1;
- else
- {
- _kernel_setenv("Sys$ReturnCode", "0");
- rval = system(cmd);
- }
-
- remove(pipes[i].name);
- }
-
- /* clean up current pipe */
- pipes[i].pmode = unopened;
- free(pipes[i].name);
- free(pipes[i].command);
- return rval;
- }
-
- /* save a string on the heap; return pointer to it */
-
- static char *strdup (const char *str)
- {
- char *p = malloc(strlen(str)+1);
-
- if (p == NULL)
- {
- fprintf(stderr,"Not enough memory to save string\n");
- exit(1);
- }
-
- return (strcpy(p,str));
- }
-
- /* Check whether a command is an OS command (binary search on the table
- * os_commands of valid OS commands).
- */
-
- static char *os_commands[] =
- {
- "access", "adfs", "alphabet", "alphabets",
- "append", "audio", "basic", "breakclr",
- "breaklist", "breakset", "build", "cat",
- "cdir", "channelvoice", "close", "configure",
- "continue", "copy", "count", "countries",
- "country", "create", "debug", "delete",
- "deskfs", "dir", "dump", "echo",
- "enumdir", "error", "eval", "ex",
- "exec", "fileinfo", "fontcat", "fontlist",
- "fx", "go", "gos", "help",
- "iconsprites", "if", "ignore", "info",
- "initstore", "key", "keyboard", "lcat",
- "lex", "lib", "list", "load",
- "memory", "memorya", "memoryi", "modules",
- "obey", "opt", "poduleload", "podules",
- "podulesave", "pointer", "print", "qsound",
- "quit", "ram", "remove", "rename",
- "rmclear", "rmensure", "rmfaster", "rmkill",
- "rmload", "rmreinit", "rmrun", "rmtidy",
- "rommodules", "run", "save", "schoose",
- "scopy", "screenload", "screensave", "sdelete",
- "set", "seteval", "setmacro", "settype",
- "sflipx", "sflipy", "sget", "shadow",
- "shellcli", "show", "showregs", "shut",
- "shutdown", "sinfo", "slist", "sload",
- "smerge", "snew", "sound", "speaker",
- "spool", "spoolon", "srename", "ssave",
- "stamp", "status", "stereo", "tempo",
- "time", "tuning", "tv", "type",
- "unplug", "unset", "up", "voices",
- "volume", "wimppalette", "wimpslot", "wimptask",
- "wipe"
- };
-
- #define NUM_CMDS (sizeof(os_commands) / sizeof(char *))
-
- static int os_cmd (char *cmd)
- {
- int low = 0;
- int high = NUM_CMDS - 1;
-
- while (low <= high)
- {
- int mid = (high + low) / 2;
- int i = cmp_cmd(cmd,os_commands[mid]);
-
- if (i == 0)
- return 1;
- else if (i < 0)
- high = mid - 1;
- else
- low = mid + 1;
- }
-
- return 0;
- }
-
- static int cmp_cmd (char *cmd, char *name)
- {
- while (*name && tolower(*cmd) == *name)
- ++name, ++cmd;
-
- if (*name)
- return (tolower(*cmd) - *name);
-
- return (*cmd != '\0' && !isspace(*cmd));
- }
-
- #ifdef test
- int main (int argc, char *argv[])
- {
- FILE *fp;
- char *cmd;
-
- if (argc <= 1)
- {
- printf("Usage Popen [cmd or Popen ]cmd\n");
- return 0;
- }
-
- cmd = argv[1];
-
- if (*cmd++ == ']')
- {
- fp = popen(cmd,"w");
- fprintf(fp,"hello\nworld\nhow\nare\nyou\n");
- pclose(fp);
- }
- else
- {
- char buf[500];
- fp = popen(cmd,"r");
- while (!feof(fp))
- {
- if (!fgets(buf,499,fp))
- {
- printf("Read error!\n");
- return 1;
- }
- buf[strlen(buf)-1] = 0;
- printf(">%s<\n", buf);
- }
- pclose(fp);
- }
-
- return 0;
- }
- #endif
-
- int unlink (const char *name)
- {
- _kernel_osfile_block blk;
-
- return (_kernel_osfile(6,name,&blk) <= 0);
- }
-
- int getch (void)
- {
- return _kernel_osrdch();
- }
-
- int getche (void)
- {
- int ch = _kernel_osrdch();
-
- _kernel_oswrch(ch);
-
- return ch;
- }
-
- int kbhit (void)
- {
- return ((_kernel_osbyte(152,0,0) & 0x00FF0000) != 0x00010000);
- }
-
- char *ecvt(double number, int ndigit, int *decpt, int *sign)
- {
- int n = 0;
- static char buf[30];
-
- /* Sort out the sign */
- if (number >= 0)
- *sign = 0;
- else
- {
- *sign = 1;
- number = -number;
- }
-
- /* Normalise the number to 0.1 <= number < 1, setting decpt */
- if (number >= 1)
- {
- while (number >= 1)
- {
- ++n;
- number /= 10.0;
- }
- }
- else if (number != 0.0 && number < 0.1)
- {
- while (number < 0.1)
- {
- --n;
- number *= 10.0;
- }
- }
- *decpt = n;
-
- sprintf(buf, "%#.*f", ndigit, number);
-
- /* Skip the leading "0." */
- return (buf+2);
- }
- #endif /* ARM */
-
- #if ATARI_ST
- #if LATTICE
-
- long _STACK = 10240;
- long _MNEED = 200000; /* reserve space for allocation (may be too large) */
-
- #include <osbind.h>
-
- /* Structure necessary for handling system time. */
- struct tm {
- short tm_year;
- short tm_mon;
- short tm_wday;
- short tm_mday;
- short tm_hour;
- short tm_min;
- short tm_sec;
- };
-
- struct tm *localtime(clock) /* fill structure with clock time */
- int clock; /* millisecond timer value, if supplied; not used */
- {
- static struct tm tv;
- unsigned int time, date;
-
- time = Tgettime();
- date = Tgetdate();
- tv.tm_year = ((date >> 9) & 0x7f) + 80;
- tv.tm_mon = ((date >> 5) & 0xf) - 1;
- tv.tm_mday = date & 0x1f;
- tv.tm_hour = (time >> 11) & 0x1f;
- tv.tm_min = (time >> 5) & 0x3f;
- tv.tm_sec = 2 * (time & 0x1f);
-
- tv.tm_wday = weekday(tv.tm_mday,tv.tm_mon+1,tv.tm_year);
- return(&tv);
- }
-
-
- weekday(day,month,year) /* find day of week from */
- short day, month, year; /* day, month, and year */
- { /* Sunday..Saturday is 0..6 */
- int index, yrndx, mondx;
-
- if(month <= 2) { /* Jan or Feb month adjust */
- month += 12;
- year -= 1;
- }
-
- yrndx = year + (year / 4) - (year / 100) + (year / 400);
- mondx = 2 * month + (3 * (month + 1)) / 5;
- index = day + mondx + yrndx + 2;
- return(index % 7);
- }
-
-
-
- time(ptime) /* return value of millisecond timer */
- int *ptime;
- {
- int tmp, ssp; /* value of supervisor stack pointer */
- static int *tmr = (int *) 0x04ba; /* addr of timer */
-
- ssp = gemdos(0x20,0); /* enter supervisor mode */
- tmp = *tmr * 5; /* get millisecond timer */
- ssp = gemdos(0x20,ssp); /* enter programmer mode */
-
- if(ptime != NULL)
- *ptime = tmp;
-
- return(tmp);
- }
-
- int brk(p)
- char *p;
- {
- char *sbrk();
- long int l, m;
-
- l = (long int)p;
- m = (long int)sbrk(0);
-
- return((lsbrk((long) (l - m)) == 0) ? -1 : 0);
- }
-
- #endif /* LATTICE */
- #endif /* ATARI_ST */
-
- #if MACINTOSH
- #if MPW
- /*
- ** Special routines for Macintosh Programmer's Workshop
- ** implementation of the Icon Programming Language
- */
-
- #include <Types.h>
- #include <Events.h>
- #include <OSUtils.h>
- #define MaxBlockX MaxBlock /* MaxBlock Icon definition conflicts */
- #undef MaxBlock /* with Mac Toolbox routine */
- #include <Memory.h>
- #define MaxBlock MaxBlockX
- #undef MaxBlockX
- #include <Errors.h>
-
- /*
- ** Initialization and Termination Routines
- */
- /*
- ** MacExit -- This function is installed by an onexit() call in MacInit
- ** -- it is called automatically when the program terminates.
- */
- void
- MacExit()
- {
- void ResetStack();
- extern Ptr MemBlock;
-
- ResetStack();
- if (MemBlock != NULL) DisposPtr(MemBlock);
- }
-
- /*
- ** MacInit -- This function is called near the beginning of execution of
- ** iconx. It is called by our own brk/sbrk initialization routine.
- */
- void
- MacInit()
- {
- atexit(MacExit);
- }
-
-
- /*
- ** Brk and Sbrk Equivalents
- */
-
- typedef Ptr caddr_t;
-
- static caddr_t MemBlock, Break, Limit;
- word xcodesize;
-
- init_brk()
- {
- static short init = 0;
- Size max, grow, size;
- char *v;
-
- if (!init) {
- init = 1;
- MacInit();
- if ((v = getenv("ICONSIZE")) != NULL) { /* if ICONSIZE defined */
- if ((size = atol(v)) <= 0) { /* if ICONSIZE negative */
- max = MaxMem(&grow);
- size = max + grow - (size < 0 ? -size : max / 4);
- }
- }
- else { /* if ICONSIZE undefined */
- size = xcodesize + mstksize + statsize + ssize + abrsize + 512;
- }
- if ((MemBlock = NewPtr(size)) == NULL) {
- syserr("problem allocating Mac memory");
- }
- Break = MemBlock;
- Limit = MemBlock + size;
- }
- return 1;
- }
-
- caddr_t
- brk(addr)
- caddr_t addr;
- {
- Size newsize;
-
- if (!init_brk()) return (caddr_t)-1;
- if (addr < MemBlock) return (caddr_t)-1;
- if (addr < Limit) Break = addr;
- else {
- newsize = addr - MemBlock;
- SetPtrSize(MemBlock, newsize);
- if (MemError() != noErr) return (caddr_t)-1;
- Break = Limit = addr;
- }
- return (caddr_t)0;
- }
-
- caddr_t
- sbrk(incr)
- int incr;
- {
- caddr_t start;
-
- if (!init_brk()) return (caddr_t)-1;
- start = Break;
- if (incr != 0) {
- if (brk(start + incr) == (caddr_t)-1) return (caddr_t)-1;
- }
- return start;
- }
-
- #endif /* MPW */
- #endif /* MACINTOSH */
-
- #if MSDOS
- int pathFind(target, buf, n)
- char target[];
- char buf[];
- int n;
- {
- char *path;
- register int i;
- int res;
- struct stat sbuf;
-
- if ((path = getenv("PATH")) == 0)
- path = "";
-
- if (!getcwd(buf, n)) { /* get current working directory */
- *buf = 0; /* may be better to do something nicer if we can't */
- return 0; /* find out where we are -- struggling to achieve */
- } /* something can be better than not trying */
-
- /* attempt to find the icode file in the current directory first */
- /* this mimicks the behavior of COMMAND.COM */
- if ((i = strlen(buf)) > 0) {
- i = buf[i - 1];
- if (i != '\\' && i != '/' && i != ':')
- strcat(buf, "/");
- }
- strcat(buf, target);
- res = stat(buf, &sbuf);
-
- while(res && *path) {
- for (i = 0; *path && *path != ';'; ++i)
- buf[i] = *path++;
- if (*path) /* skip the ; or : separator */
- ++path;
- if (i == 0) /* skip empty fragments in PATH */
- continue;
- if (i > 0 && buf[i - 1] != '/' && buf[i - 1] != '\\' &&
- buf[i - 1] != ':')
- buf[i++] = '/';
- strcpy(buf + i, target);
- res = stat(buf, &sbuf);
- /* exclude directories (and any other nasties) from selection */
- if (res == 0 && sbuf.st_mode & S_IFDIR)
- res = -1;
- }
-
- if (res != 0)
- *buf = 0;
- return res == 0;
- }
-
- FILE *pathOpen(fname, mode)
- char *fname;
- char *mode;
- {
- char buf[150 + 1];
- int i, use = 1;
-
- for( i = 0; buf[i] = fname[i]; ++i)
- /* find out if a path has been given in the file name */
- if (buf[i] == '/' || buf[i] == ':' || buf[i] == '\\')
- use = 0;
-
- /* If a path has been given with the file name, don't bother to
- use the PATH */
-
- if (use && !pathFind(fname, buf, 150))
- return 0;
-
- return fopen(buf, mode);
- }
- #if INTEL_386
- /* sbrk(incr) - adjust the break value by incr.
- * Returns the new break value, or -1 if unsuccessful.
- */
-
- pointer sbrk(incr)
- msize incr;
- {
- static pointer base = 0; /* base of the sbrk region */
- static pointer endofmem, curr;
- pointer result;
- union REGS rin, rout;
-
- if (!base) { /* if need to initialize */
- rin.w.eax = 0x80004800; /* use DOS allocate function with max */
- rin.w.ebx = 0xffffffff; /* request to determine size of free */
- intdos(&rin, &rout); /* memory (including virtual memory. */
- rin.w.ebx = rout.w.ebx; /* DOS allocate all of memory. */
- intdos(&rin, &rout);
- if (rout.w.cflag)
- return (pointer)-1;
- curr = base = (pointer)rout.w.eax;
- endofmem = (pointer)((char *)base + rin.w.ebx);
- }
-
- if ((char *)curr + incr > (char *)endofmem)
- return (pointer)-1;
- result = curr;
- curr = (pointer)((char *)curr + incr);
- return result;
-
- }
-
- /* brk(addr) - set the break address to the given value, rounded up to a page.
- * returns 0 if successful, -1 if not.
- */
-
- int brk(addr)
- pointer addr;
- {
- int result;
- result = sbrk((char *)addr - (char *)sbrk(0)) == (pointer)-1 ? -1 : 0;
- return result;
- }
-
- #endif /* INTEL_386 */
-
- #if TURBO
- extern unsigned _stklen = 16 * 1024;
- #endif /* TURBO */
-
- #if LATTICE
-
- #include <error.h>
-
- int _stack = (8 * 1024);
- long int _mneed = (20 * 1024);
-
- extern long int *sp;
- long int **xsp = &sp; /* Used for rswitch.asm .. since 'sp' is a reserved */
- /* symbol for the assembler.. */
-
- extern char *statend; /* Indicator for when to use malloc for _GETBF */
-
- int brk(p)
- char *p;
- {
- char *sbrk();
- long int l, m;
-
- l = (long int)p;
- m = (long int)sbrk((word)0);
-
- if( lsbrk((long) (l - m) ) == 0) return -1;
- else return 0;
- }
-
- novalue abort() /* Abort set to 'dump' icon data area.. */
- {
- #ifdef DeBugIconx
- blkdump();
- #endif /* DeBugIconx */
- fflush(stderr);
- fcloseall();
- _exit(1);
- }
- #endif /* LATTICE */
- #endif /* MSDOS */
-
- #if MVS || VM
- #if SASC
- #include <options.h>
- char _linkage = _OPTIMIZE;
-
- #if MVS
- char *_style = "tso:"; /* use dsnames as file names */
- #define SYS_OSVS
- #else /* MVS */
- #define SYS_CMS
- #endif /* MVS */
- int _mneed = 512000; /* size of sbrk-managed region */
-
- #define RES_SIGNAL
- #define RES_COPROC
- #define RES_IOUTIL
- #define RES_DSNAME
- #define RES_FILEDEF
- #define RES_UNITREC
-
- #include <resident.h>
-
- #endif /* SASC */
- #endif /* MVS || VM */
-
- #if OS2
- novalue abort()
- {
- #ifdef DeBugIconx
- blkdump();
- #endif
- fflush(stderr);
- fcloseall();
- _exit(1);
- }
- /* Pipe support for OS/2 */
- #include <fcntl.h>
- #include <stddef.h>
- #include <process.h>
- #include <errno.h>
-
- #define INCL_DOS
- #include <os2.h>
-
- static int _pipes[_NFILE];
-
- /*
- * popen("command",mode)
- *
- * cmd = command to be passed to shell. (CMD.EXE or comspec->)
- * mode = "r" | "w"
- */
- FILE *
- popen(cmd, mode)
- char *cmd;
- char *mode;
- {
-
- int whandle, rhandle;
- int phandle, chandle, shandle;
- int rc;
- char *cmdshell;
-
- /* Validate */
- if(cmd == NULL || mode == NULL) return NULL;
- if(tolower(*mode) != 'r' && tolower(*mode) != 'w')
- return NULL;
-
- /* Create the pipe */
- if (DosMakePipe(&rhandle, &whandle, BUFSIZ) < 0)
- return NULL;
-
- /* Dup STDIN or STDOUT to the pipe */
- if (*mode == 'r') {
- /* Dup stdout */
- phandle = rhandle;
- chandle = whandle;
- shandle = dup(1); /* Save STDOUT */
- rc = dup2(chandle, 1);
- } else {
- /* Dup stdin */
- phandle = whandle;
- chandle = rhandle;
- shandle = dup(0); /* Save STDIN */
- rc = dup2(chandle, 0);
- }
- if (rc < 0) {
- perror("dup2");
- return NULL;
- }
- close(chandle);
-
- /* Make sure that we don't pass this handle on */
- DosSetFHandState(phandle, OPEN_FLAGS_NOINHERIT);
-
- /* Invoke the child, remember its processid */
- cmdshell = getenv("COMSPEC");
- if (cmdshell == NULL) cmdshell = "CMD.EXE";
-
- _pipes[chandle] = spawnlp(P_NOWAIT, cmdshell, cmdshell,"/c",cmd, NULL);
-
- /* Clean up by reestablishing our STDIN/STDOUT */
- if (*mode == 'r')
- rc = dup2(shandle, 1);
- else
- rc = dup2(shandle, 0);
- if (rc < 0) {
- perror("dup2");
- return NULL;
- }
- close(shandle);
-
- return fdopen(phandle, mode);
- }
- pclose(ptr)
- FILE *ptr;
- {
- int status, pnum;
-
- pnum = fileno(ptr);
- fclose(ptr);
-
- /* Now wait for child to end */
- cwait(&status, _pipes[pnum], WAIT_GRANDCHILD);
-
- return status;
- }
-
- /* End of pipe support for OS/2 */
- #endif /* OS2 */
-
- #if UNIX
- #ifdef ATTM32
-
- /*
- * This file contains the routine necessary to allocate legal AT&T
- * 3B2/15/4000 stack space for co-expression stacks.
- *
- * Legal stack region begins at 0xC0020000, and UNIX will grow stack space
- * up to 50 Megabytes. 0xC0030000 should provide plenty of room for
- * main C stack growth. Each time coexpr_salloc() is called, it
- * adds mstksize (max main stack size) and returns a new address,
- * meaning each coexpression stack is potentially as large as the main stack.
- */
-
- /*
- * coexp_salloc() - return pointer in legal stack space for start
- * of a coexpression stack.
- */
-
- pointer coexp_salloc()
- {
- static pointer sp = 0xC0030000 ; /* pointer to stack region */
-
- sp += mstksize;
- return sp;
- }
- #endif /* ATTM32 */
-
- #endif /* UNIX */
-
- #if VMS
- #passthru #define LIB_GET_EF LIB$GET_EF
- #passthru #define SYS_CREMBX SYS$CREMBX
- #passthru #define LIB_FREE_EF LIB$FREE_EF
- #passthru #define DVI__DEVNAM DVI$_DEVNAM
- #passthru #define SYS_GETDVIW SYS$GETDVIW
- #passthru #define SYS_DASSGN SYS$DASSGN
- #passthru #define LIB_SPAWN LIB$SPAWN
- #passthru #define SYS_QIOW SYS$QIOW
- #passthru #define IO__WRITEOF IO$_WRITEOF
- #passthru #define SYS_WFLOR SYS$WFLOR
- #passthru #define sys_expreg sys$expreg
- #passthru #define STS_M_SUCCESS STS$M_SUCCESS
- #passthru #define sys_cretva sys$cretva
-
- typedef struct _descr {
- int length;
- char *ptr;
- } descriptor;
-
- typedef struct _pipe {
- long pid; /* process id of child */
- long status; /* exit status of child */
- long flags; /* LIB$SPAWN flags */
- int channel; /* MBX channel number */
- int efn; /* Event flag to wait for */
- char mode; /* the open mode */
- FILE *fptr; /* file pointer (for fun) */
- unsigned running : 1; /* 1 if child is running */
- } Pipe;
-
- Pipe _pipes[_NFILE]; /* one for every open file */
-
- #define NOWAIT 1
- #define NOCLISYM 2
- #define NOLOGNAM 4
- #define NOKEYPAD 8
- #define NOTIFY 16
- #define NOCONTROL 32
- #define SFLAGS (NOWAIT|NOKEYPAD|NOCONTROL)
-
- /*
- * popen - open a pipe command
- * Last modified 2-Apr-86/chj
- *
- * popen("command", mode)
- */
-
- FILE *popen(cmd, mode)
- char *cmd;
- char *mode;
- {
- FILE *pfile; /* the Pfile */
- Pipe *pd; /* _pipe database */
- descriptor mbxname; /* name of mailbox */
- descriptor command; /* command string descriptor */
- descriptor nl; /* null device descriptor */
- char mname[65]; /* mailbox name string */
- int chan; /* mailbox channel number */
- int status; /* system service status */
- int efn;
- struct {
- short len;
- short code;
- char *address;
- char *retlen;
- int last;
- } itmlst;
-
- if (!cmd || !mode)
- return (0);
- LIB_GET_EF(&efn);
- if (efn == -1)
- return (0);
- if (_tolower(mode[0]) != 'r' && _tolower(mode[0]) != 'w')
- return (0);
- /* create and open the mailbox */
- status = SYS_CREMBX(0, &chan, 0, 0, 0, 0, 0);
- if (!(status & 1)) {
- LIB_FREE_EF(&efn);
- return (0);
- }
- itmlst.last = mbxname.length = 0;
- itmlst.address = mbxname.ptr = mname;
- itmlst.retlen = &mbxname.length;
- itmlst.code = DVI__DEVNAM;
- itmlst.len = 64;
- status = SYS_GETDVIW(0, chan, 0, &itmlst, 0, 0, 0, 0);
- if (!(status & 1)) {
- LIB_FREE_EF(&efn);
- return (0);
- }
- mname[mbxname.length] = '\0';
- pfile = fopen(mname, mode);
- if (!pfile) {
- LIB_FREE_EF(&efn);
- SYS_DASSGN(chan);
- return (0);
- }
- /* Save file information now */
- pd = &_pipes[fileno(pfile)]; /* get Pipe pointer */
- pd->mode = _tolower(mode[0]);
- pd->fptr = pfile;
- pd->pid = pd->status = pd->running = 0;
- pd->flags = SFLAGS;
- pd->channel = chan;
- pd->efn = efn;
- /* fork the command */
- nl.length = strlen("_NL:");
- nl.ptr = "_NL:";
- command.length = strlen(cmd);
- command.ptr = cmd;
- status = LIB_SPAWN(&command,
- (pd->mode == 'r') ? 0 : &mbxname, /* input file */
- (pd->mode == 'r') ? &mbxname : 0, /* output file */
- &pd->flags, 0, &pd->pid, &pd->status, &pd->efn, 0, 0, 0, 0);
- if (!(status & 1)) {
- LIB_FREE_EF(&efn);
- SYS_DASSGN(chan);
- return (0);
- } else {
- pd->running = 1;
- }
- return (pfile);
- }
-
- /*
- * pclose - close a pipe
- * Last modified 2-Apr-86/chj
- *
- */
- pclose(pfile)
- FILE *pfile;
- {
- Pipe *pd;
- int status;
- int fstatus;
-
- pd = fileno(pfile) ? &_pipes[fileno(pfile)] : 0;
- if (pd == NULL)
- return (-1);
- fflush(pd->fptr); /* flush buffers */
- fstatus = fclose(pfile);
- if (pd->mode == 'w') {
- status = SYS_QIOW(0, pd->channel, IO__WRITEOF, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- SYS_WFLOR(pd->efn, 1 << (pd->efn % 32));
- }
- SYS_DASSGN(pd->channel);
- LIB_FREE_EF(&pd->efn);
- pd->running = 0;
- return (fstatus);
- }
-
- /*
- * redirect(&argc,argv,nfargs) - redirect standard I/O
- * int *argc number of command arguments (from call to main)
- * char *argv[] command argument list (from call to main)
- * int nfargs number of filename arguments to process
- *
- * argc and argv will be adjusted by redirect.
- *
- * redirect processes a program's command argument list and handles redirection
- * of stdin, and stdout. Any arguments which redirect I/O are removed from the
- * argument list, and argc is adjusted accordingly. redirect would typically be
- * called as the first statement in the main program.
- *
- * Files are redirected based on syntax or position of command arguments.
- * Arguments of the following forms always redirect a file:
- *
- * <file redirects standard input to read the given file
- * >file redirects standard output to write to the given file
- * >>file redirects standard output to append to the given file
- *
- * It is often useful to allow alternate input and output files as the
- * first two command arguments without requiring the <file and >file
- * syntax. If the nfargs argument to redirect is 2 or more then the
- * first two command arguments, if supplied, will be interpreted in this
- * manner: the first argument replaces stdin and the second stdout.
- * A filename of "-" may be specified to occupy a position without
- * performing any redirection.
- *
- * If nfargs is 1, only the first argument will be considered and will
- * replace standard input if given. Any arguments processed by setting
- * nfargs > 0 will be removed from the argument list, and again argc will
- * be adjusted. Positional redirection follows syntax-specified
- * redirection and therefore overrides it.
- *
- */
-
-
- redirect(argc,argv,nfargs)
- int *argc, nfargs;
- char *argv[];
- {
- int i;
-
- i = 1;
- while (i < *argc) { /* for every command argument... */
- switch (argv[i][0]) { /* check first character */
- case '<': /* <file redirects stdin */
- filearg(argc,argv,i,1,stdin,"r");
- break;
- case '>': /* >file or >>file redirects stdout */
- if (argv[i][1] == '>')
- filearg(argc,argv,i,2,stdout,"a");
- else
- filearg(argc,argv,i,1,stdout,"w");
- break;
- default: /* not recognized, go on to next arg */
- i++;
- }
- }
- if (nfargs >= 1 && *argc > 1) /* if positional redirection & 1 arg */
- filearg(argc,argv,1,0,stdin,"r"); /* then redirect stdin */
- if (nfargs >= 2 && *argc > 1) /* likewise for 2nd arg if wanted */
- filearg(argc,argv,1,0,stdout,"w");/* redirect stdout */
- }
-
-
-
- /* filearg(&argc,argv,n,i,fp,mode) - redirect and remove file argument
- * int *argc number of command arguments (from call to main)
- * char *argv[] command argument list (from call to main)
- * int n argv entry to use as file name and then delete
- * int i first character of file name to use (skip '<' etc.)
- * FILE *fp file pointer for file to reopen (typically stdin etc.)
- * char mode[] file access mode (see freopen spec)
- */
-
- filearg(argc,argv,n,i,fp,mode)
- int *argc, n, i;
- char *argv[], mode[];
- FILE *fp;
- {
- if (strcmp(argv[n]+i,"-")) /* alter file if arg not "-" */
- fp = freopen(argv[n]+i,mode,fp);
- if (fp == NULL) { /* abort on error */
- fprintf(stderr,"%%can't open %s",argv[n]+i);
- exit(ErrorExit);
- }
- for ( ; n < *argc; n++) /* move down following arguments */
- argv[n] = argv[n+1];
- *argc = *argc - 1; /* decrement argument count */
- }
-
- /* Special versions of sbrk() and brk() for use by Icon under VMS.
- * #defines in define.h actually rename these to vms_brk and vms_sbrk.
- *
- * For historical reasons, Icon assumes it can repeatedly call brk/sbrk
- * and always get contiguous chunks. This was made to work under Unix by
- * overloading the definitions of malloc and friends, the only other callers
- * of sbrk, and making them return Icon-managed memory.
-
- * Under VMS, sbrk is not the lowest-level system interface. It gets memory
- * from underlying VMS routines such as SYS$EXPREG. These routines are also
- * called by others, for example when a file is opened; so successive sbrk
- * calls may return nonadjacent chunks. This makes overloading malloc and
- * friends futile.
- *
- * The routines below replace sbrk and brk for Icon (only) under VMS. They
- * provide the continuously growing memory Icon needs without relying on
- * special privileges or unusually large quotas. Like the Unix solution and
- * earlier VMS attempts, this is an empirical solution and may need further
- * revision as the system changes. But we hope not.
- *
- * The Icon interpreter is loaded beginning at address 0 and grows upward as
- * it requests more memory through sbrk. The C stack grows downward from
- * 0x7FFFFFFF. We're going to draw a line to divide the address space, then
- * force the C and VMS runtime systems to put anything they need above it;
- * then sbrk can grow the program region unimpeded up to the line.
- *
- * The line is drawn MAXMEM bytes beyond the start of the sbrk region. MAXMEM
- * is an environment variable (logical name to VMS) with a default as given in
- * define.h. Large values cost CPU and real time expended at process exit; we
- * don't know why. On an 8600 the cost was very roughly .04 CP sec / megabyte.
- *
- * When first called, sbrk expands the program region by one page to get a
- * starting address. A limit address is calculated by adding MAXMEM. A single
- * page created just below the limit address "draws the line" and causes the
- * VMS runtime system to allocate anything it needs above that point. sbrk
- * creates pages between base and limit as needed.
- *
- * Possible errors and their manifestations:
- *
- * MAXMEM too large to initialize sbrk:
- * error in startup code: value of MAXMEM too large
- *
- * MAXMEM too small to initialize sbrk:
- * error in startup code: value of MAXMEM too small
- *
- * MAXMEM too small for subsequent brk/sbrk growth
- * Run-time error 351: insufficient MAXMEM limit
- *
- * MAXMEM okay but insufficient user quota for needed memory:
- * Run-time error 303: unable to expand memory region
- *
- * unexpected ("can't happen") failures of system calls:
- * these produce their standard VMS error message
- *
- * unexpected intrusion into the sbrk region by the runtime system:
- * unknown, but undoubtedly ugly
- */
-
-
- #define PageSize 512 /* size of a VMS page */
- #define MaxP0 0x40000000 /* first address beyond the P0 region */
-
- word memsize = MaxMem; /* set from environment variable MAXMEM */
-
-
- /* sbrk(incr) - adjust the break value by incr, rounding up to a page.
- * returns the new break value, or -1 if unsuccessful.
- */
-
- char *
- sbrk(incr)
- int incr;
- {
- static char *base; /* base of the sbrk region */
- static char *curr; /* current break value (end+1) */
- static char *limit; /* region limit ("the line") */
- char *range[2], *p; /* scratch for system calls */
- int s; /* status return from calls */
-
- /* initialization code */
- if (!base) {
- s = sys_expreg(1,range,0,0); /* expand P0 to get base address */
- if (!(s & STS_M_SUCCESS))
- exit(s); /* couldn't get one page?! */
- base = curr = range[0]; /* initialize empty sbrk region */
- memsize = (memsize + PageSize - 1) & -PageSize;
- /* round memsize to page boundary */
- limit = base + memsize; /* calculate sbrk region limit*/
- if (limit > MaxP0)
- limit = MaxP0; /* limit to legal values */
- if (limit <= base)
- error("value of MAXMEM too small"); /* can't even start */
- range[0] = range[1] = limit-1;
- s = sys_cretva(range,range,0); /* get a page there to draw the line */
- if (!(s & STS_M_SUCCESS))
- error("value of MAXMEM too large"); /* can't even start */
- }
-
- if (incr > 0) {
-
- /* grow the region */
- if (curr + incr > limit) /* check address space available */
- fatalerr(351,NULL); /* oops, MAXMEM too small */
- range[0] = curr;
- range[1] = curr + incr - 1;
- s = sys_cretva(range,range,0); /* ask for the pages */
- if (!(s & STS_M_SUCCESS))
- return (char *) -1; /* failed, quota exceeded */
- curr = range[1] + 1; /* set new break value as returned */
-
- } else if (incr < 0) {
-
- /* shrink the region (not expected to be used). does not actually
- * return the memory, but does make it available for reuse. */
- curr -= -incr & -PageSize;
- }
-
- /* return the current break value */
- return curr;
- }
-
-
-
-
- /* brk(addr) - set the break address to the given value, rounded up to a page.
- * returns 0 if successful, -1 if not.
- */
-
- char *
- brk(addr)
- char *addr;
- {
- return ((sbrk(addr-sbrk(0))) == (char *) -1 ? (char *) -1 : 0);
- }
- #endif /* VMS */
-
- /*
- * End of operating-system specific code.
- */
-
- static char x; /* avoid empty module */
-